package cmd

import (
	"fmt"
	"gvm/instructions/base"
	"gvm/rtda"
	"gvm/rtda/heap"
	"strings"
)

type JVM struct {
	// 参数
	cmd *Cmd
	// 类加载器
	classLoader *heap.ClassLoader
	// main线程
	mainThread *rtda.JThread
}

func (self *JVM) Start() {
	self.initVM()
	self.execMain()
}

func (self *JVM) initVM() {
	vmClass := self.classLoader.LoadClass("sun/misc/VM")
	base.InitClass(self.mainThread, vmClass)
	interpret(self.mainThread)
}

func (self *JVM) execMain() {
	className := strings.Replace(self.cmd.Class, ".", "/", -1)
	mainClass := self.classLoader.LoadClass(className)
	mainMethod := mainClass.GetMainMethod()
	if mainMethod == nil {
		fmt.Println("Main method not found in class%s\n", self.cmd.Class)
	}
	argArr := self.createArgsArray()
	frame := self.mainThread.NewFrame(mainMethod)
	frame.LocalVars().SetRef(0, argArr)
	self.mainThread.PushJFrame(frame)
	interpret(self.mainThread)

}

func (self *JVM) createArgsArray() *heap.Object {
	stringClass := self.classLoader.LoadClass("java/lang/String")
	argsLen := uint(len(self.cmd.Args))
	argsArr := stringClass.ArrayClass().NewArray(argsLen)
	jArgs := argsArr.Refs()
	for i, arg := range self.cmd.Args {
		jArgs[i] = heap.JString(self.classLoader, arg)
	}
	return argsArr
}
